from typing import List

from backend.app.database.db_es import es_conn
from backend.app.database.db_pinecone import rdb_conn
from backend.app.schemas.device import DeviceInfoSchema


# 已废弃
class TenderDeviceMatchChain:
    """【Pinecone向量数据库】按照最大相关性查询"""
    _top_k = 3  # 需要查处几个相似

    def __init__(self, shop_id: int, namespace: str = "", index_name: str = "avl"):
        self._rdb = rdb_conn.get_rds(namespace=namespace, index_name=index_name)
        self._sid = shop_id

    @staticmethod
    def get_rdb():
        return rdb_conn.get_rds()

    async def base_search(self, query: str, **kwargs):
        rdb = self.get_rdb()

        condition = dict()
        if self._sid > 0:
            condition["sid"] = self._sid
        result = await rdb.amax_marginal_relevance_search(
            # result = await rdb.asimilarity_search(
            query=query,
            k=self._top_k,
            filter=condition,
            fetch_k=50,
            lambda_mult=0.8,
            namespace=kwargs.get("namespace")
        )
        return result

    async def search(self, query: str, **kwargs):
        result = await self.base_search(query, **kwargs)
        return self.format_result(result)

    async def search_list(self, query: str, **kwargs):
        """搜索设备列表"""
        result = await self.base_search(query, **kwargs)
        return self.format_to_list(result)

    @staticmethod
    def format_to_list(score_docs: List) -> List[DeviceInfoSchema]:
        """将搜索结果转为设备列表"""
        lists = []
        if not score_docs:
            return lists
        for data in score_docs:
            item = DeviceInfoSchema(**data.metadata)
            lists.append(item)
        return lists

    @staticmethod
    def format_result(score_docs: List) -> DeviceInfoSchema:
        device = DeviceInfoSchema()
        if not score_docs:
            return device
        child_list = []
        for data in score_docs:
            item = DeviceInfoSchema(**data.metadata)
            if device.gid < 1:
                device = item
            else:
                child_list.append(item)
        if device and device.gid > 0:
            device.child_list = child_list
        return device


# 已废弃
class TenderDeviceMatchScoreChain:
    """【Pinecone向量数据库】 按照评分查询"""
    _top_k = 3  # 需要查处几个相似

    def __init__(self, shop_id: int, namespace: str = "", index_name: str = "avl", top_key: int = 3):
        self._rdb = rdb_conn.get_rds(namespace=namespace, index_name=index_name)
        self._sid = shop_id
        if top_key:
            self._top_k = top_key

    @staticmethod
    def get_rdb():
        return rdb_conn.get_rds()

    @staticmethod
    def get_client(index_name: str = "avl"):
        return es_conn.get_langchain_client()

    async def base_search(self, query: str, **kwargs):
        rdb = self.get_client()
        condition = dict()
        if self._sid > 0:
            condition["sid"] = self._sid
        result = await rdb.asimilarity_search_with_score(
            query=query,
            k=self._top_k,
            filter=condition,
            namespace=kwargs.get("namespace")
        )
        return result

    async def search(self, query: str, **kwargs):
        """设备列表搜索-->返回主要设备和相似设备"""
        result = await self.base_search(query, **kwargs)
        return self.format_result(result)

    async def search_list(self, query: str, **kwargs):
        """搜索设备列表"""
        result = await self.base_search(query, **kwargs)
        return self.format_to_list(result)

    @staticmethod
    def format_to_list(score_docs: List) -> List[DeviceInfoSchema]:
        """将搜索结果转为设备列表"""
        lists = []
        if not score_docs:
            return lists
        for data, score in score_docs:
            item = DeviceInfoSchema(**data.metadata)
            lists.append(item)
        return lists

    @staticmethod
    def format_result(score_docs: List) -> DeviceInfoSchema:
        """列出结果中评分最高的设备，其他设备列表子设备列表"""
        device = DeviceInfoSchema()
        if not score_docs:
            return device
        for data, score in score_docs:
            item = DeviceInfoSchema(**data.metadata)
            if device.gid < 1:
                device = item
            else:
                device.child_list.append(item)
        return device
